package com.smap.control;

import java.util.Date;

import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.user.client.Window;
import com.smap.common.Callback;
import com.smap.common.GeoAPI;
import com.smap.core.Layer;
import com.smap.core.XY;
import com.smap.event.MapEvent;

public class NavigateControl extends AbstractControl {

	int[] rect = null;

	int min = 4;
	int max = 18;

	public void setRange(int min, int max) {
		this.min = min;
		this.max = max;
	}

	public void onEvent(MapEvent evt) {
		if ("draging".equals(evt.type)) {
			if (evt.btn == 1) {

				if ((evt.moveX > 0) && (evt.moveY > 0)) {

					Context2d ctx = map.getScreen();
					if (rect != null) {
						ctx.clearRect(rect[0] - 1, rect[1] - 1, rect[2] + 2,
								rect[3] + 2);
					} else {
						rect = new int[4];
					}
					rect[0] = MapEvent.START_X;
					rect[1] = MapEvent.START_Y;
					rect[2] = evt.moveX;
					rect[3] = evt.moveY;
					ctx.setStrokeStyle("blue");
					ctx.setGlobalAlpha(1);
					ctx.setLineWidth(2);
					ctx.strokeRect(rect[0], rect[1], rect[2], rect[3]);
				}
			} else {
				map.setScreenOffset(evt.moveX, evt.moveY);
				map.setCursor("move");
			}
		} else if ("dragend".equals(evt.type)) {
			if (rect != null) {
				Context2d ctx = map.getScreen();
				ctx.clearRect(rect[0] - 1, rect[1] - 1, rect[2] + 2,
						rect[3] + 2);
				rect[0] = rect[0] - map.getWidth() / 2;
				rect[1] = rect[1] - map.getHeight() / 2;
				map.zoomTo(rect);
				rect = null;
			} else {
				map.updateLocation();
			}
			map.setCursor(null);

		} else if ("mousewheel".equals(evt.type)) {
			int zoom = map.getZoom();
			if (evt.deltaY > 0) {
				zoom--;
			} else {
				zoom++;
			}
			if (inRange(zoom))
				map.zoom(null, zoom);
		} else if ("dbclick".equals(evt.type)) {
			XY newCentre = map.pixelToMap(new XY(evt.x, evt.y));
			map.zoom(newCentre, 15);
		}

		// if it's mobile then gives the smooth effect
		if (Window.Navigator.getUserAgent().toLowerCase().contains("android")) {
			if ("dragstart".equals(evt.type)) {
				start_location = map.getCentre();
				start_time = new Date().getTime();
			} else if ("dragend".equals(evt.type)) {
				double v = 1000 / (new Date().getTime() - start_time);
				if (v > 1) {
					XY current = map.getCentre();
					double x = start_location.x
							+ (current.x - start_location.x) * v;
					double y = start_location.y
							+ (current.y - start_location.y) * v;
					map.zoom(new XY(x, y), null);
				}
			}
		}

		// set range
		if (MapEvent.EVT_MAP_DRAWN.equals(evt.type)) {
			if (this.map.getZoom() >= max) {
				toolBar.disable("zoomIn");
			} else {
				toolBar.enable("zoomIn");
			}
			if (this.map.getZoom() <= min) {
				toolBar.disable("zoomOut");
			} else {
				toolBar.enable("zoomOut");
			}
		}
	}

	XY start_location;
	long start_time;

	boolean inRange(int zoom) {
		return (zoom <= max && zoom >= min);
	}

	@Override
	public void execute(String cmd) {
		if ("zoomIn".equals(cmd)) {
			map.zoomIn();
		} else if ("zoomOut".equals(cmd)) {
			map.zoomOut();
		} else if ("currentLocation".equals(cmd)) {
			GeoAPI geo = new GeoAPI(new Callback() {
				public void exe(Object... obj) {
					Double lon = (Double) obj[0];
					Double lat = (Double) obj[1];
					map.zoomByLonLat(lon, lat, null);
				}
			});
			geo.getLoc();
		} else if ("switchBaseLayer".equals(cmd)) {
			Layer layer = map.getLayers().get(0);
			layer.setType(null);
			map.draw(false);
		}

	}

	@Override
	public String[] getCmd() {
		return new String[] { "zoomIn", "zoomOut", "currentLocation",
				"switchBaseLayer" };
	}

	@Override
	void init() {
		
	}
}
